package conf

import (
	"encoding/json"
	"flag"
	"github.com/ghodss/yaml"
	"github.com/go-kratos/kratos/v2/log"
	"io/ioutil"
	"os"
	"strconv"
	"time"
)

var (
	confPath  string
	region    string
	zone      string
	deployEnv string
	host      string
	weight    int64

	// Conf config
	Conf *Config
)

var Logger *log.Helper

func init() {
	var (
		defHost, _   = os.Hostname()
		defWeight, _ = strconv.ParseInt(os.Getenv("WEIGHT"), 10, 32)
	)
	flag.StringVar(&confPath, "conf", "configs/logic.yaml", "default config path")
	flag.StringVar(&host, "host", defHost, "machine hostname. or use default machine hostname.")
	flag.Int64Var(&weight, "weight", defWeight, "load balancing weight, or use WEIGHT env variable, value: 10 etc.")
}


func InitConfig()  error {
	yml :=  loadConfig()
	Conf = Default()
	err := ApplyYAML(Conf,yml)
	return err

}

func ApplyYAML(config *Config,yml string)  error {
	js,err := yaml.YAMLToJSON([]byte(yml))
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(js,config)
	if err != nil {
		panic(err)
	}
	return nil
}

func loadConfig() string {
	file,err := os.Open(confPath)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	fd,err := ioutil.ReadAll(file)
	if err != nil {
		panic(err)
	}
	return  string(fd)
}


// Default new a config with specified defualt value.
func Default() *Config {
	return &Config{
		Env:       &Env{Host: host, Weight: weight},
		HTTPServer: &HTTPServer{
			Network:      "tcp",
			Addr:         "3111",
			ReadTimeout:  time.Second,
			WriteTimeout: time.Second,
		},
		RPCClient: &RPCClient{Dial: time.Second, Timeout: time.Second},
		RPCServer: &RPCServer{
			Network:           "tcp",
			Addr:              "3119",
			Timeout:          time.Second,
			IdleTimeout:       time.Second * 60,
			MaxLifeTime:       time.Hour * 2,
			ForceCloseWait:    time.Second * 20,
			KeepAliveInterval: time.Second * 60,
			KeepAliveTimeout:  time.Second * 20,
		},
		Backoff: &Backoff{MaxDelay: 300, BaseDelay: 3, Factor: 1.8, Jitter: 1.3},
	}
}
type Consul struct {
	Addr string
}

// Config config.
type Config struct {
	Env        *Env
	RPCClient  *RPCClient
	RPCServer  *RPCServer
	HTTPServer *HTTPServer
	Kafka      *Kafka
	Redis      *Redis
	Backoff    *Backoff
	Regions    map[string][]string
	Consul *Consul
	Log *Log
}

type Log struct {
	Path string
}

// Env is env config.
type Env struct {
	Host      string
	Weight    int64
}



// Backoff backoff.
type Backoff struct {
	MaxDelay  int32
	BaseDelay int32
	Factor    float32
	Jitter    float32
}

// Redis .
type Redis struct {
	Network      string
	Addr         string
	Auth         string
	Active       int
	Idle         int
	DialTimeout  time.Duration
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
	IdleTimeout  time.Duration
	Expire       time.Duration
}

// Kafka .
type Kafka struct {
	Topic   string
	Brokers []string
}

// RPCClient is RPC client config.
type RPCClient struct {
	Dial    time.Duration
	Timeout time.Duration
}

// RPCServer is RPC server config.
type RPCServer struct {
	Network           string
	Addr              string
	Timeout           time.Duration
	IdleTimeout       time.Duration
	MaxLifeTime       time.Duration
	ForceCloseWait    time.Duration
	KeepAliveInterval time.Duration
	KeepAliveTimeout  time.Duration
}

// HTTPServer is http server config.
type HTTPServer struct {
	Network      string
	Addr         string
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
}
